package com.easpeed.comon.utils

import android.app.Application
import com.blankj.utilcode.util.ToastUtils
import com.easpeed.common.CommonConsts
import com.easpeed.comon.bean.AppOperateBean
import com.easpeed.comon.bean.ChannelSettingBean
import com.easpeed.comon.bean.ChartControlBean
import com.easpeed.comon.bean.JsonBean
import com.easpeed.comon.bean.LineChartExpand
import com.easpeed.comon.bean.OtdrBean
import com.easpeed.comon.bean.BtnStatusBean
import com.easpeed.comon.bean.DataBattery
import com.easpeed.comon.bean.HighlightBean
import com.easpeed.comon.bean.SsxfBean
import com.easpeed.comon.bean.UserOnlineStatus
import com.easpeed.comon.bean.operateFunc
import com.easpeed.comon.consts.ConstsApi
import com.easpeed.elevator.bean.EventInfo
import com.easpeed.elevator.bean.EventThreshold
import com.easpeed.user.bean.UserTcpBean
import com.easpeed.user.utils.TcpClient
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.greenrobot.eventbus.EventBus
import java.util.Timer
import java.util.TimerTask
import java.util.UUID

/**
 * Created by bigyu on 2024/10/31 13:22
 * com.easpeed.user.utils
 */
object SocketHelper {
    @JvmStatic
    var isUserOnline = false

    @JvmStatic
    var userName: String? = ""

    private var application: Application? = null

    @JvmStatic
    fun init(application: Application) {
        this.application = application
    }

    var appType: Byte = 0x01

    fun initAppType() {
        if (CommonConsts.Type == "user") {
            appType = 0x02
        } else {
            appType = 0x01
        }
    }

    private var result = object : ((TcpData) -> Unit) {
        override fun invoke(p1: TcpData) {
            commonMainThread {
                if (p1.code == TcpCode.NEED_RECONNECT) {
                    stopSocket()
                    reConnect()
                    return@commonMainThread
                }
                val newTcpData = onlineStatusCheck(p1)
                listenerMap.forEach {
                    it.value.invoke(newTcpData)
                }
            }
        }
    }
    var tcpClient: TcpClient? = null


    private var timerReConnect: Timer? = null
    private var isReConnect = false
    fun reConnect() {
        timerReConnect = Timer()
        if (!isReConnect) {
            isReConnect = true
            timerReConnect?.schedule(object : TimerTask() {
                override fun run() {
                    try {
                        if (isConnected()) {
                            isReConnect = false
                            timerReConnect?.cancel()
                            return
                        }
                        "************重连服务************".print()
                        startSocket(ConstsApi.socketHost, ConstsApi.socketPort, CommonConsts.targetDeviceId)
                    } catch (e: Exception) {
                        com.bigyu.utils.Logger.e("TAG", "重连服务失败: ${e.message}")
                    }
                }
            }, 5000, 5000)
        }
    }

    @JvmStatic
    fun isConnected(): Boolean {
        return tcpClient?.isConnected() == true
    }

    @JvmStatic
    fun startSocket(host: String, port: Int, deviceId: String) {
        if (tcpClient?.isConnected() != true) {
            release()
            tcpClient = TcpClient(host, port, deviceId = deviceId, appType = appType, result = result)
            tcpClient?.startHeartbeat()
        } else {
            com.bigyu.utils.Logger.e("TAG", "startSocket: 已连接设备，请勿重复连接")
            result(TcpData().connectFailed("已连接设备，请勿重复连接"))
        }
    }

    @JvmStatic
    fun sendCommand(command: String, data: String) {
        if (command == SendCommand.commandDvsDataRequest.bytesToHex()) {
            val currentTimeMillis = System.currentTimeMillis()
            com.bigyu.utils.Logger.e("TAG", "dvs数据发送间隔 ${currentTimeMillis - lastDvsResponseTime}")
            lastDvsResponseTime = currentTimeMillis
        }
        if (isConnected()) {
            val start1 = System.currentTimeMillis()
            val tcpBean = UserTcpBean(deviceId = CommonConsts.targetDeviceId, command = command, data = data, appType = byteArrayOf(appType).bytesToHex())
            val start2 = System.currentTimeMillis()
            val createTcpPacket = tcpBean.createTcpPacket()
            val start3 = System.currentTimeMillis()
            tcpClient?.sendData(createTcpPacket)
            val start4 = System.currentTimeMillis()

//            Logger.e("TAG", "sendCommand: ${start2 - start1}   ${start3 - start2}   ${start4 - start3}" )
        } else {
            com.bigyu.utils.Logger.e("TAG", "sendCommand: 未连接设备")
        }
    }

    @JvmStatic
    fun sendCommandTest(command: String, data: String) {
        if (isConnected()) {

//            createTcpPacketV2(CommonConsts.targetDeviceId, byteArrayOf(appType).bytesToHex(), command, data)
        } else {
            com.bigyu.utils.Logger.e("TAG", "sendCommand: 未连接设备")
        }
    }

    @JvmStatic
    fun sendCommand(command: ByteArray, data: ByteArray) {
        if (isConnected()) {
            val createTcpPacket = createTcpPacket(CommonConsts.targetDeviceId, appType, command, data)
            tcpClient?.sendData(createTcpPacket)
        } else {
            com.bigyu.utils.Logger.e("TAG", "sendCommand: 未连接设备")
        }
    }

    @JvmStatic
    fun sendUpdateName() {
        if (isConnected()) {
            tcpClient?.sendUserName()
        } else {
            com.bigyu.utils.Logger.e("TAG", "sendCommand: 未连接设备")
        }
    }

    private var lastDvsResponseTime = 0L

    @JvmStatic
    fun sendCommand(command: ByteArray, data: String) {

        sendCommand(command.bytesToHex(), data)
    }

    @JvmStatic
    fun sendCommand(command: ByteArray, data: JsonBean?) {
        sendCommand(command.bytesToHex(), Gson().toJson(data))
    }


    fun release() {
    }

    private var listenerMap = mutableMapOf<String, (TcpData) -> Unit>()

    @JvmStatic
    fun addResultListener(tag: String, listener: (TcpData) -> Unit) {
        listenerMap[tag] = listener
    }

    @JvmStatic
    fun removeResultListener(tag: String) {
        listenerMap.remove(tag)
    }

    @JvmStatic
    fun stopSocket() {
        tcpClient?.stopHeartbeat()
        tcpClient = null
    }


    private fun onlineStatusCheck(tcpBean: TcpData): TcpData {
        var newTcpData = tcpBean
        tcpBean.data?.let {
            tcpBean.commandStr = it.command
            tcpBean.bundleStr = it.data
            when (it.command) {
                SendCommand.errorCommand.bytesToHex() -> {
                    //上线失败
//                    newTcpData = TcpData().connectFailed(TcpCommand.getError(it.data))
                    ToastUtils.showShort(TcpCommand.getError(it.originalData) + "${it.originalData} ${it.data}")
                }

                SendCommand.commandUserOnlineOperate.bytesToHex() -> {
                    if (!isUser()) {
                        isUserOnline = true
                        userName = it.data
                        EventBus.getDefault().post(UserOnlineStatus(isUserOnline))
                    }
                }

                SendCommand.commandUserOfflineOperate.bytesToHex() -> {
                    if (!isUser()) {
                        isUserOnline = false
                        userName = it.data
                        EventBus.getDefault().post(UserOnlineStatus(isUserOnline))
                    }
                }

                SendCommand.commandOnlineState.bytesToHex() -> {
                }

                //dvs开关命令
                SendCommand.changeDvsStateCommand.bytesToHex() -> {


                }

                SendCommand.commandResponse.bytesToHex() -> {
                    ToastUtils.showShort(it.data)
                }

                SendCommand.commandEventTable.bytesToHex() -> {
                    try {
                        com.bigyu.utils.Logger.e("TAG", "${it.data} ")
                        val type = object : TypeToken<ArrayList<EventInfo?>?>() {
                        }.type
                        val eventTableJson: ArrayList<EventInfo> = Gson().fromJson(it.data, type)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandSsxfResponseOperate.bytesToHex() -> {
                    try {
                        val eventTableJson: SsxfBean = Gson().fromJson(it.data, SsxfBean::class.java)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandExpandResponse.bytesToHex() -> {
                    try {
                        val eventTableJson: LineChartExpand = Gson().fromJson(it.data, LineChartExpand::class.java)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandSyncHideOtdrData.bytesToHex(), SendCommand.commandSyncYuhuiData.bytesToHex() -> {
                    try {
                        val eventTableJson: BtnStatusBean = Gson().fromJson(it.data, BtnStatusBean::class.java)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandSyncLineData.bytesToHex() -> {
                    try {
                        val eventTableJson: HighlightBean = Gson().fromJson(it.data, HighlightBean::class.java)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandDvsDataResponse.bytesToHex() -> {
                    try {

                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandOTDRDataResponse.bytesToHex() -> {
                    try {
                        com.bigyu.utils.Logger.e("TAG", "${it.data} ")

                        val type = object : TypeToken<ArrayList<DoubleArray>>() {
                        }.type
                        val eventTableJson: ArrayList<DoubleArray> = Gson().fromJson(it.data, type)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandMatrixResponse.bytesToHex() -> {
                    try {
                        com.bigyu.utils.Logger.e("TAG", "${it.data} ")
//                        val type = object : TypeToken<ChartControlBean>() {
//                        }.type
                        val eventTableJson: ChartControlBean = Gson().fromJson(it.data, ChartControlBean::class.java)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandOTDRDataRequest.bytesToHex() -> {
                    try {
                        com.bigyu.utils.Logger.e("TAG", "${it.data} ")
                        val eventTableJson: OtdrBean = Gson().fromJson(it.data, OtdrBean::class.java)
                        tcpBean.any = eventTableJson
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.changeChannelCommand.bytesToHex() -> {
                    //切换频道
                    com.bigyu.utils.Logger.d("TAG", "收到切换通道的消息 ${it.data}")
                    try {
                        val bean = Gson().fromJson(it.data, ChannelSettingBean::class.java)
                        tcpBean.any = bean
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandAppOperate.bytesToHex() -> {
                    //app操作
                    if (!isUser()) {
                        try {
                            val bean = Gson().fromJson(it.data, AppOperateBean::class.java)
                            tcpBean.any = bean
//                            bean.operateFunc(application)
                        } catch (e: Exception) {
                            e.printStackTrace()
                        }
                    }
                }

                SendCommand.commandSyncBattery.bytesToHex() -> {
                    //设备给用户发送电量数据
                    try {
                        val bean = Gson().fromJson(it.data, DataBattery::class.java)
                        tcpBean.any = bean
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandSyncOTDRSetting.bytesToHex() -> {
                    try {
                        val bean = Gson().fromJson<HashMap<String, String>>(it.data, object : TypeToken<HashMap<String, String>>() {}.type)
                        tcpBean.any = bean
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandOTDRRedRequest.bytesToHex() -> {
                    try {
                        val bean = Gson().fromJson<HashMap<String, String>>(it.data, object : TypeToken<HashMap<String, String>>() {}.type)
                        tcpBean.any = bean
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandEventThresholdRequest.bytesToHex() -> {
                    try {
                        val bean = Gson().fromJson<EventThreshold>(it.data, object : TypeToken<EventThreshold>() {}.type)
                        tcpBean.any = bean
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                SendCommand.commandSyncDVSSetting.bytesToHex() -> {
                    try {
                        val bean = Gson().fromJson<HashMap<String, String>>(it.data, object : TypeToken<HashMap<String, String>>() {}.type)
                        tcpBean.any = bean
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                else -> {

                }
            }
        }

        return newTcpData
    }

    /**
     * 生成8字节的唯一ID
     */
    fun generateUniqueIdFromUUID(): String {
        val uuid = UUID.randomUUID()
        val mostSignificantBits = uuid.mostSignificantBits
        val uniqueId = ByteArray(4) // 只取前4字节
        for (i in 0..3) {
            uniqueId[i] = (mostSignificantBits shr (8 * (7 - i)) and 0xFF).toByte()
        }
        return uniqueId.joinToString(separator = "") { String.format("%02X", it) }
    }


}
